1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 /***
24 * @author Brian Goetz
25 */
26
27 package org.webmacro.parser;
28
29 import org.webmacro.engine.BlockBuilder;
30
31 /***
32 * ParserBlockBuilder extends BlockBuilder, and should only be used by
33 * the WMParser_impl parser. It adds methods for eating trailing
34 * <WHITESPACE> or <WHITESPACE> <NL> <WHITESPACE> that precede directives.
35 * It assumes that literal text will not span elements (true for the
36 * current parser) so if the parser changes, this will need to change too.
37 */
38
39
40 public class ParserBlockBuilder extends BlockBuilder
41 {
42
43 private int literalMark = 0;
44
45 public ParserBlockBuilder ()
46 {
47 super();
48 }
49
50 public ParserBlockBuilder (String name)
51 {
52 super(name);
53 }
54
55 /*** Mark the last character in the block as being a literal (quoted
56 * with backslash) so we don't eat trailing quoted whitespace.
57 */
58 final public void markLiteral ()
59 {
60 literalMark = size();
61 }
62
63 private final static boolean isSpaceChar (char c)
64 {
65 return (c == ' ' || c == '\t');
66 }
67
68 private final static int eatWs (String s, int pos)
69 {
70 while (pos >= 0 && isSpaceChar(s.charAt(pos)))
71 pos--;
72 return pos;
73 }
74
75 private final static int eatOneWs (String s, int pos)
76 {
77 if (pos >= 0 && isSpaceChar(s.charAt(pos)))
78 pos--;
79 return pos;
80 }
81
82 private final static int eatNl (String s, int pos)
83 {
84 if (pos >= 0)
85 {
86 if (s.charAt(pos) == '\r')
87 pos--;
88 else if (s.charAt(pos) == '\n')
89 {
90 pos--;
91 if (pos >= 0 && s.charAt(pos) == '\r')
92 pos--;
93 }
94 }
95 return pos;
96 }
97
98 final public void eatTrailingWs ()
99 {
100 int i, j;
101
102 i = size() - 1;
103 if (i < 0 || i + 1 == literalMark)
104 return;
105
106 Object o = elementAt(i);
107 if (!(o instanceof String))
108 return;
109 String s = (String) o;
110 j = eatWs(s, s.length() - 1);
111
112 if (j < 0)
113 remove(i);
114 else if (j < s.length() - 1)
115 setElementAt(s.substring(0, j + 1), i);
116 markLiteral();
117 }
118
119
120 final public void eatTrailingWsNl ()
121 {
122 int i, j;
123
124 i = size() - 1;
125 if (i < 0 || i + 1 == literalMark)
126 return;
127
128 Object o = elementAt(i);
129 if (!(o instanceof String))
130 return;
131 String s = (String) o;
132 j = eatWs(s, s.length() - 1);
133 j = eatNl(s, j);
134
135 if (j < 0)
136 remove(i);
137 else if (j < s.length() - 1)
138 setElementAt(s.substring(0, j + 1), i);
139 markLiteral();
140 }
141
142 final public void eatTrailingWsNlWs ()
143 {
144 int i, j;
145
146 i = size() - 1;
147 if (i < 0 || i + 1 == literalMark)
148 return;
149
150 Object o = elementAt(i);
151 if (!(o instanceof String))
152 return;
153 String s = (String) o;
154 j = eatWs(s, s.length() - 1);
155 j = eatNl(s, j);
156 j = eatWs(s, j);
157
158 if (j < 0)
159 remove(i);
160 else if (j < s.length() - 1)
161 setElementAt(s.substring(0, j + 1), i);
162 markLiteral();
163 }
164
165 final public void eatOneWs ()
166 {
167 int i, j;
168
169 i = size() - 1;
170 if (i < 0 || i + 1 == literalMark)
171 return;
172
173 Object o = elementAt(i);
174 if (!(o instanceof String))
175 return;
176 String s = (String) o;
177 j = eatOneWs(s, s.length() - 1);
178
179 if (j < 0)
180 remove(i);
181 else if (j < s.length() - 1)
182 setElementAt(s.substring(0, j + 1), i);
183 markLiteral();
184 }
185
186 final public void eatLeadingWsNl ()
187 {
188 int i, j, l;
189
190 i = size() - 1;
191 if (i < 0 || i + 1 == literalMark)
192 return;
193
194 Object o = elementAt(i);
195 if (!(o instanceof String))
196 return;
197 String s = (String) o;
198 j = 0;
199 l = s.length();
200 while (j < l && isSpaceChar(s.charAt(j)))
201 j++;
202 if (j < l)
203 {
204 if (s.charAt(j) == '\r')
205 j++;
206 else if (s.charAt(j) == '\n')
207 {
208 j++;
209 if (j < l && s.charAt(j) == '\r')
210 j++;
211 }
212 }
213
214 if (j >= l)
215 remove(i);
216 else if (j > 0)
217 setElementAt(s.substring(j), i);
218 markLiteral();
219 }
220
221 final public boolean directiveOk ()
222 {
223 if (size() == 0 || size() == literalMark)
224 return true;
225 else
226 {
227 Object o = elementAt(size() - 1);
228
229
230
231
232
233
234
235 if (!(o instanceof String) || (((String)o).length() == 0))
236 return true;
237 else
238 {
239 String s = (String) o;
240 char ch = s.charAt(s.length() - 1);
241 if (ch == '=' || ch == '\'' || ch == '\"' || ch == ':'
242 || Character.isLetterOrDigit(ch))
243 return false;
244 }
245 }
246 return true;
247 }
248 }